from rest_framework import viewsets, permissions
from rest_framework.response import Response
from rest_framework.decorators import action
from django.db.models import F
from django.shortcuts import get_object_or_404
from django.http import Http404

from .models import Article, Category, UserLike, UserBookmark
from .serializers import ArticleSerializer, CategorySerializer
from django_filters.rest_framework import DjangoFilterBackend
from blog.tasks import increment_views
from utils.filters import ArticleFilter
from rest_framework.permissions import IsAuthenticated
from utils.permissions import IsAdminUserOrReadOnly
class ArticleViewSet(viewsets.ModelViewSet):
    queryset = Article.objects.filter(status=Article.STATUS_PUBLISHED)
    serializer_class = ArticleSerializer
    filter_backends = [DjangoFilterBackend]
    filterset_class = ArticleFilter
    lookup_field = 'slug'

    def get_permissions(self):
        """
        设置权限:
        - 读取文章列表和详情: 允许任何人
        - 创建、更新和删除文章: 仅认证用户
        - 点赞和收藏: 仅认证用户
        """
        if self.action in ['list', 'retrieve']:
            permission_classes = [permissions.AllowAny]
        else:
            permission_classes = [permissions.IsAuthenticated]
        return [permission() for permission in permission_classes]

    def get_queryset(self):
        """优化查询性能"""
        return super().get_queryset().select_related(
            'author', 'category'
        ).prefetch_related(
            'tags'
        ).order_by('-published_time')

    def retrieve(self, request, *args, **kwargs):
        """记录浏览量（异步更新）"""
        instance = self.get_object()
        # 异步任务示例（需配置 Celery）
        increment_views.delay(instance.id)
        return super().retrieve(request, *args, **kwargs)

    @action(detail=True, methods=['post'])
    def like(self, request, slug=None):
        """点赞/取消点赞文章"""
        article = self.get_object()
        user = request.user
        
        # 检查是否已经点赞
        like_exists = UserLike.objects.filter(user=user, post=article).exists()
        
        if like_exists:
            # 取消点赞
            UserLike.objects.filter(user=user, post=article).delete()
            article.likes = F('likes') - 1
            message = '取消点赞成功'
        else:
            # 添加点赞
            UserLike.objects.create(user=user, post=article)
            article.likes = F('likes') + 1
            message = '点赞成功'
            
        article.save()
        article.refresh_from_db()
        
        return Response({
            'message': message,
            'likes': article.likes
        })

    @action(detail=True, methods=['post'])
    def bookmark(self, request, slug=None):
        """收藏/取消收藏文章"""
        article = self.get_object()
        user = request.user
        
        # 检查是否已经收藏
        bookmark_exists = UserBookmark.objects.filter(user=user, post=article).exists()
        
        if bookmark_exists:
            # 取消收藏
            UserBookmark.objects.filter(user=user, post=article).delete()
            article.collects = F('collects') - 1
            message = '取消收藏成功'
        else:
            # 添加收藏
            UserBookmark.objects.create(user=user, post=article)
            article.collects = F('collects') + 1
            message = '收藏成功'
            
        article.save()
        article.refresh_from_db()
        
        return Response({
            'message': message,
            'collects': article.collects
        })

    @action(detail=False, methods=['get'], permission_classes=[IsAuthenticated])
    def bookmarked(self, request):
        user = request.user
        articles = user.bookmarked_posts.all()
        page = self.paginate_queryset(articles)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        serializer = self.get_serializer(articles, many=True)
        return Response(serializer.data)

    # 支持通过ID查询
    def get_object(self):
        """
        重写此方法以支持通过ID查询和处理重复slug的情况
        """
        lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
        value = self.kwargs.get(lookup_url_kwarg)
        
        # 尝试识别是否为ID查询
        if value and value.isdigit():
            # 如果是数字，则直接通过ID查询并返回
            return get_object_or_404(Article, id=int(value))
        
        # 如果是通过slug查询，确保只返回最新的一篇文章
        queryset = self.filter_queryset(self.get_queryset())
        filter_kwargs = {self.lookup_field: value}
        
        # 获取符合条件的所有文章，并按更新时间降序排序，只取第一个
        obj = queryset.filter(**filter_kwargs).order_by('-updated_time').first()
        if obj is None:
            raise Http404(f"未找到匹配的 {self.lookup_field}={value} 的文章")
            
        return obj


class CategoryViewSet(viewsets.ModelViewSet):
    queryset = Category.objects.all()
    serializer_class = CategorySerializer
    permission_classes = [IsAdminUserOrReadOnly]
    # 只有管理员才能操作
    # permission_classes = [IsAdminUser]
    # permission_classes = [IsAdminUserOrReadOnly]
    def get_paginated_response(self, data):
        # 当size=all时返回原始数组结构
        if self.request.query_params.get('size', '').lower() == 'all':
            return Response(data)
        return super().get_paginated_response(data)